use std::path::{Path, PathBuf};
use log::{debug};

/// 生成安全的文件查找候选列表
/// 只返回通过安全检查的候选路径
pub fn get_safe_file_candidates(requested_file: &PathBuf) -> Vec<PathBuf> {
    let mut safe_candidates = Vec::new();
    let static_base = "static";

    // 生成所有可能的候选路径
    let mut potential_candidates = Vec::new();

    // 1. 构建基础路径
    let mut base_path = PathBuf::from(static_base);
    base_path.push(requested_file);
    potential_candidates.push(base_path.clone());

    // 2. 如果原始路径没有扩展名，尝试添加后缀
    let extensions = [
        "html",
        "htm",
        "md",
        "txt"
    ];
    if requested_file.extension().is_none() {
        for extension in &extensions {
            // 寻找对应后缀名的文件
            let mut html_path = PathBuf::from(static_base);
            html_path.push(requested_file);
            html_path.set_extension(extension);
            if html_path.exists() {
                potential_candidates.push(html_path);
            }
            // 寻找对应文件夹下的index文件
            let mut index_path = base_path.clone();
            // 如果携带index，则跳过
            if index_path.iter().last().unwrap() == "index" {
                continue;
            }
            index_path.push("index.");
            index_path.set_extension(extension);
            potential_candidates.push(index_path);
        }
    }

    // 对每个候选路径进行安全检查
    for candidate in potential_candidates {
        if let Some(candidate_str) = candidate.to_str() {
            if is_subpath(static_base, candidate_str) {
                debug!("候选路径通过安全检查: {:?}", candidate);
                safe_candidates.push(candidate);
            } else {
                debug!("候选路径未通过安全检查或不存在对应文件，已跳过: {:?}", candidate);
            }
        } else {
            debug!("无法转换候选路径为字符串，已跳过: {:?}", candidate);
        }
    }

    debug!("生成了 {} 个安全的候选路径", safe_candidates.len());
    safe_candidates
}

/// 判断当前文件夹下是否有对应文件
fn is_subpath(base: &str, requested: &str) -> bool {
    let base = Path::new(base).canonicalize().ok();
    let requested = Path::new(requested).canonicalize().ok();
    if let (Some(base), Some(requested)) = (base, requested) {
        requested.starts_with(&base)
    } else {
        false
    }
}